home *** CD-ROM | disk | FTP | other *** search
/ isnet Internet / Isnet Internet CD.iso / prog / hiz / 09 / 09.exe / adynware.exe / perl / lib / site / HTTP / Response.pm < prev    next >
Encoding:
Perl POD Document  |  1999-12-28  |  8.5 KB  |  359 lines

  1.  
  2. package HTTP::Response;
  3.  
  4.  
  5. =head1 NAME
  6.  
  7. HTTP::Response - Class encapsulating HTTP Responses
  8.  
  9. =head1 SYNOPSIS
  10.  
  11.  require HTTP::Response;
  12.  
  13. =head1 DESCRIPTION
  14.  
  15. The C<HTTP::Response> class encapsulate HTTP style responses.  A
  16. response consist of a response line, some headers, and a (potential
  17. empty) content. Note that the LWP library will use HTTP style
  18. responses also for non-HTTP protocol schemes.
  19.  
  20. Instances of this class are usually created and returned by the
  21. C<request()> method of an C<LWP::UserAgent> object:
  22.  
  23.  ...
  24.  $response = $ua->request($request)
  25.  if ($response->is_success) {
  26.      print $response->content;
  27.  } else {
  28.      print $response->error_as_HTML;
  29.  }
  30.  
  31. =head1 METHODS
  32.  
  33. C<HTTP::Response> is a subclass of C<HTTP::Message> and therefore
  34. inherits its methods.  The inherited methods are header(),
  35. push_header(), remove_header(), headers_as_string(), and content().
  36. The header convenience methods are also available.  See
  37. L<HTTP::Message> for details.
  38.  
  39. =cut
  40.  
  41.  
  42. require HTTP::Message;
  43. @ISA = qw(HTTP::Message);
  44.  
  45. use HTTP::Status ();
  46. use URI::URL ();
  47. use strict;
  48.  
  49.  
  50. =head2 $r = new HTTP::Response ($rc, [$msg, [$header, [$content]]])
  51.  
  52. Constructs a new C<HTTP::Response> object describing a response with
  53. response code C<$rc> and optional message C<$msg>.
  54.  
  55. =cut
  56.  
  57. sub new
  58. {
  59.     my($class, $rc, $msg, $header, $content) = @_;
  60.     my $self = bless new HTTP::Message $header, $content;
  61.     $self->code($rc);
  62.     $self->message($msg);
  63.     $self;
  64. }
  65.  
  66.  
  67. sub clone
  68. {
  69.     my $self = shift;
  70.     my $clone = bless $self->HTTP::Message::clone;
  71.     $clone->code($self->code);
  72.     $clone->message($self->message);
  73.     $clone->request($self->request->clone) if $self->request;
  74.     $clone;
  75. }
  76.  
  77. =head2 $r->code([$code])
  78.  
  79. =head2 $r->message([$message])
  80.  
  81. =head2 $r->request([$request])
  82.  
  83. =head2 $r->previous([$previousResponse])
  84.  
  85. These methods provide public access to the member variables.  The
  86. first two containing respectively the response code and the message
  87. of the response.
  88.  
  89. The request attribute is a reference the request that gave this
  90. response.  It does not have to be the same request as passed to the
  91. $ua->request() method, because there might have been redirects and
  92. authorization retries in between.
  93.  
  94. The previous attribute is used to link together chains of responses.
  95. You get chains of responses if the first response is redirect or
  96. unauthorized.
  97.  
  98. =cut
  99.  
  100. sub code      { shift->_elem('_rc',      @_); }
  101. sub message   { shift->_elem('_msg',     @_); }
  102. sub previous  { shift->_elem('_previous',@_); }
  103. sub request   { shift->_elem('_request', @_); }
  104.  
  105. sub status_line
  106. {
  107.     my $self = shift;
  108.     my $code = $self->{'_rc'}  || "000";
  109.     my $mess = $self->{'_msg'} || "?";
  110.     return "$code $mess";
  111. }
  112.  
  113. =head2 $r->base
  114.  
  115. Returns the base URL for this response.  The return value will be a
  116. reference to a URI::URL object.
  117.  
  118. The base URL is obtained from one the following sources (in priority
  119. order):
  120.  
  121. =over 4
  122.  
  123. =item 1.
  124.  
  125. Embedded in the document content, for instance <BASE HREF="...">
  126. in HTML documents.
  127.  
  128. =item 2.
  129.  
  130. A "Content-Base:" or a "Content-Location:" header in the response.
  131.  
  132. For backwards compatability with older HTTP implementations we will
  133. also look for the "Base:" header.
  134.  
  135.  
  136. =item 3.
  137.  
  138. The URL used to request this response. This might not be the original
  139. URL that was passed to $ua->request() method, because we might have
  140. received some redirect responses first.
  141.  
  142. =back
  143.  
  144. When the LWP protocol modules produce the HTTP::Response object, then
  145. any base URL embedded in the document (step 1) will already have
  146. initialized the "Content-Base:" header. This means that this method
  147. only perform the last 2 steps (the content is not always available
  148. either).
  149.  
  150. =cut
  151.  
  152. sub base
  153. {
  154.     my $self = shift;
  155.     my $base = $self->header('Content-Base')     ||  # HTTP/1.1
  156.                $self->header('Content-Location') ||  # HTTP/1.1
  157.                $self->header('Base')             ||  # backwards compatability HTTP/1.0
  158.                $self->request->url;
  159.     $base = URI::URL->new($base) unless ref $base;
  160.     $base;
  161. }
  162.  
  163.  
  164. =head2 $r->as_string()
  165.  
  166. Method returning a textual representation of the request.  Mainly
  167. useful for debugging purposes. It takes no arguments.
  168.  
  169. =cut
  170.  
  171. sub as_string
  172. {
  173.     require HTTP::Status;
  174.     my $self = shift;
  175.     my @result = ("--- $self ---");
  176.     my $code = $self->code;
  177.     push(@result, "RC: $code (" . HTTP::Status::status_message($code) . ")" );
  178.     push(@result, 'Message: ' . $self->message);
  179.     push(@result, '');
  180.     push(@result, $self->headers_as_string);
  181.     my $content = $self->content;
  182.     if ($content) {
  183.     push(@result, $self->content);
  184.     }
  185.     push(@result, ("-" x 35));
  186.     join("\n", @result, "");
  187. }
  188.  
  189. =head2 $r->is_info
  190.  
  191. =head2 $r->is_success
  192.  
  193. =head2 $r->is_redirect
  194.  
  195. =head2 $r->is_error
  196.  
  197. These methods indicate if the response was informational, sucessful, a
  198. redirection, or an error.
  199.  
  200. =cut
  201.  
  202. sub is_info     { HTTP::Status::is_info     (shift->{'_rc'}); }
  203. sub is_success  { HTTP::Status::is_success  (shift->{'_rc'}); }
  204. sub is_redirect { HTTP::Status::is_redirect (shift->{'_rc'}); }
  205. sub is_error    { HTTP::Status::is_error    (shift->{'_rc'}); }
  206.  
  207.  
  208. =head2 $r->error_as_HTML()
  209.  
  210. Return a string containing a complete HTML document indicating what
  211. error occurred.  This method should only be called when $r->is_error
  212. is TRUE.
  213.  
  214. =cut
  215.  
  216. sub error_as_HTML
  217. {
  218.     my $self = shift;
  219.     my $msg = $self->{'_msg'} || 'Unknown';
  220.     my $title = 'An Error Occurred';
  221.     my $code = $self->code;
  222.     return <<EOM;
  223. <HTML>
  224. <HEAD>
  225. <TITLE>
  226. $title
  227. </TITLE>
  228. </HEAD>
  229. <BODY>
  230. <H1>$title</h1>
  231. $code - $msg
  232. </BODY>
  233. </HTML>
  234. EOM
  235. }
  236.  
  237.  
  238. =head2 $r->current_age
  239.  
  240. This function will calculate the "current age" of the response as
  241. specified by E<lt>draft-ietf-http-v11-spec-07> section 13.2.3.  The
  242. age of a response is the time since it was sent by the origin server.
  243. The returned value is a number representing the age in seconds.
  244.  
  245. =cut
  246.  
  247. sub current_age
  248. {
  249.     my $self = shift;
  250.     my $response_time = $self->client_date;
  251.     my $date = $self->date;
  252.  
  253.     my $age = 0;
  254.     if ($response_time && $date) {
  255.     $age = $response_time - $date;  # apparent_age
  256.     $age = 0 if $age < 0;
  257.     }
  258.  
  259.     my $age_v = $self->header('Age');
  260.     if ($age_v && $age_v > $age) {
  261.     $age = $age_v;   # corrected_received_age
  262.     }
  263.  
  264.     my $request = $self->request;
  265.     if ($request) {
  266.     my $request_time = $request->date;
  267.     if ($request_time) {
  268.         $age += $response_time - $request_time;
  269.     }
  270.     }
  271.     if ($response_time) {
  272.     $age += time - $response_time;
  273.     }
  274.     return $age;
  275. }
  276.  
  277.  
  278. =head2 $r->freshness_lifetime
  279.  
  280. This function will calculate the "freshness lifetime" of the response
  281. as specified by E<lt>draft-ietf-http-v11-spec-07> section 13.2.4.  The
  282. "freshness lifetime" is the length of time between the generation of a
  283. response and its expiration time.  The returned value is a number
  284. representing the freshness lifetime in seconds.
  285.  
  286. If the response does not contain an "Expires" or a "Cache-Control"
  287. header, then this function will apply some simple heuristic based on
  288. 'Last-Modified' to determine a suitable lifetime.
  289.  
  290. =cut
  291.  
  292. sub freshness_lifetime
  293. {
  294.     my $self = shift;
  295.  
  296.     my @cc = $self->header('Cache-Control');
  297.     if (@cc) {
  298.     my $cc;
  299.     for $cc (@cc) {
  300.         my $cc_dir;
  301.         for $cc_dir (split(/\s*,\s*/, $cc)) {
  302.         if ($cc_dir =~ /max-age\s*=\s*(\d+)/i) {
  303.             return $1;
  304.         }
  305.         }
  306.     }
  307.     }
  308.  
  309.     my $date = $self->date || $self->client_date || time;      
  310.     my $expires = $self->expires;
  311.     unless ($expires) {
  312.     my $last_modified = $self->last_modified;
  313.     if ($last_modified) {
  314.         my $h_exp = ($date - $last_modified) * 0.10;  # 10% since last-mod
  315.         if ($h_exp < 60) {
  316.         return 60;  # minimum
  317.         } elsif ($h_exp > 24 * 3600) {
  318.         return 24 * 3600;
  319.         }
  320.         return $h_exp;
  321.     } else {
  322.         return 3600;  # 1 hour is fallback when all else fails
  323.     }
  324.     }
  325.     return $expires - $date;
  326. }
  327.  
  328.  
  329. =head2 $r->is_fresh
  330.  
  331. Returns TRUE if the response is fresh, based on the values of
  332. freshness_lifetime() and current_age().  If the response is not longer
  333. fresh, then it has to be refetched or revalidated by the origin
  334. server.
  335.  
  336. =cut
  337.  
  338. sub is_fresh
  339. {
  340.     my $self = shift;
  341.     $self->freshness_lifetime > $self->current_age;
  342. }
  343.  
  344.  
  345. =head2 $r->fresh_until
  346.  
  347. Returns the time when this entiy is no longer fresh.
  348.  
  349. =cut
  350.  
  351. sub fresh_until
  352. {
  353.     my $self = shift;
  354.     return $self->freshness_lifetime - $self->current_age + time;
  355. }
  356.  
  357.  
  358. 1;
  359.